package com.yesep.learn.design.behavioral.template_method;

import com.yesep.learn.design.common.pojo.*;
import com.yesep.learn.design.common.util.*;

import java.util.*;

/**
 * 模板方法模式（Template Method Pattern）是一种行为型设计模式，其核心思想是在操作中定义算法的框架，将一些步骤延迟到子类中实现。
 * 通过这种方式，可以在不改变算法结构的前提下，通过扩展子类来重新定义算法的某些特定步骤，从而实现代码的复用和扩展。
 * 以下是对模板方法模式的详细解析：
 * <p>
 * 一、定义与结构
 * 定义：模板方法模式定义了一个操作中的算法框架，而将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下，重新定义算法的某些特定步骤。
 * <p>
 * 结构：模板方法模式主要包含以下角色：
 * <p>
 * 抽象父类（Abstract Class）：定义了一个或多个抽象方法（基本操作），以及一个模板方法（具体方法）。模板方法定义了算法的骨架，它会调用一个或多个抽象方法。
 * 具体子类（Concrete Classes）：继承自抽象父类，并实现其中的抽象方法。这些具体子类提供了算法的具体实现细节。
 * 二、工作原理
 * 模板方法模式的工作原理是通过在抽象父类中定义一个算法的框架（即模板方法），这个框架中包含了一些固定的步骤和一些需要子类实现的抽象方法。子
 * 类通过继承抽象父类并实现其中的抽象方法，来提供算法的具体实现细节。当调用模板方法时，它会按照定义的顺序执行固定步骤，并在适当的时候调用子类提供的具体实现。
 * <p>
 * 三、优点
 * 提高代码复用性：模板方法模式通过定义算法的框架，将公共部分提取到抽象父类中，使得子类可以复用父类中的代码。
 * 增强扩展性：子类可以在不改变算法结构的前提下，通过实现抽象方法来提供具体的实现细节，从而实现对算法的扩展。
 * 符合开闭原则：模板方法模式对扩展开放，对修改关闭，即在不修改现有代码的前提下，可以通过增加新的子类来扩展功能。
 * 四、缺点
 * 设计复杂度增加：每个不同的实现都需要定义一个子类，这会导致类的个数增加，系统更加庞大，设计也更加抽象。
 * 代码可读性降低：模板方法中的步骤越多，其维护工作就可能会越困难，因为需要理解整个算法的流程以及各个步骤之间的关系。
 * 可能违反里氏替换原则：通过子类抑制默认步骤实现可能会导致违反里氏替换原则，即子类对象能够替换掉父类对象并且不会破坏原有程序的正确性。
 * 五、应用场景
 * 模板方法模式适用于以下场景：
 * <p>
 * 当一组算法具有相同的逻辑结构，但具体实现有所不同时。
 * 当希望在不改变算法结构的前提下，通过扩展子类来重新定义算法的某些步骤时。
 * 当需要将算法的实现细节封装起来，只暴露出高层接口供调用者使用时。
 * 六、实例
 * 以游戏角色创建过程为例，可以定义一个游戏角色基类（GameCharacter），它定义了一个创建角色的算法框架（即模板方法），包括初始化属性、选择武器和装备防具等步骤。
 * 然后，可以定义具体的子类（如战士Warrior和法师Mage），它们将实现这些步骤中的特定细节。
 * 通过这种方式，可以在不改变创建角色算法结构的前提下，通过扩展具体的子类来创建不同类型的游戏角色。
 */
public class Main {
    public static void main(String[] args) {
        List<Goods> goodsList = DemoUtil.createGoodsList();
        NormalOrder normalOrder = new NormalOrder(goodsList);
        checkout(normalOrder);
        WeekenOrder weekenOrder = new WeekenOrder(goodsList);
        checkout(weekenOrder);

    }

    private static void checkout(ShoppingOrder order) {
        try {
            order.checkout();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}
